﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SM
{
    public static class ByteUtil
    {
        internal static byte[] AsciiBytes(string s)
        {
            byte[] bytes = new byte[s.Length];
            for (int i = 0; i < s.Length; i++)
            {
                bytes[i] = (byte)s[i];
            }
            return bytes;
        }

        internal static byte[] HexToByteArray(this string hexString)
        {
            byte[] bytes = new byte[hexString.Length / 2];
            for (int i = 0; i < hexString.Length; i += 2)
            {
                string s = hexString.Substring(i, 2);
                bytes[i / 2] = byte.Parse(s, NumberStyles.HexNumber, null);
            }
            return bytes;
        }

        internal static string ByteArrayToHex(this byte[] bytes)
        {
            var builder = new StringBuilder(bytes.Length * 2);
            foreach (byte b in bytes)
            {
                builder.Append(b.ToString("X2"));
            }
            return builder.ToString();
        }

        internal static string ByteArrayToHex(this byte[] bytes, int len)
        {
            return ByteArrayToHex(bytes).Substring(0, len * 2);
        }

        internal static byte[] RepeatByte(byte b, int count)
        {
            byte[] value = new byte[count];
            for (int i = 0; i < count; i++)
            {
                value[i] = b;
            }
            return value;
        }

        internal static byte[] SubBytes(this byte[] bytes, int startIndex, int length)
        {
            byte[] res = new byte[length];
            Array.Copy(bytes, startIndex, res, 0, length);
            return res;
        }

        internal static byte[] XOR(this byte[] value)
        {
            byte[] res = new byte[value.Length];
            for (int i = 0; i < value.Length; i++)
            {
                res[i] ^= value[i];
            }
            return res;
        }

        internal static byte[] XOR(this byte[] valueA, byte[] valueB)
        {
            int len = valueA.Length;
            byte[] res = new byte[len];
            for (int i = 0; i < len; i++)
            {
                res[i] = (byte)(valueA[i] ^ valueB[i]);
            }
            return res;
        }

        internal static byte[] FromHexstring(string summary)
        {
            char[] rawChars = summary.ToUpper().ToCharArray();
            int hexChars = 0;

            for (int i = 0; i < rawChars.Length; ++i)
            {
                if (rawChars[i] >= '0' && rawChars[i] <= '9' || rawChars[i] >= 'A' && rawChars[i] <= 'F')
                {
                    ++hexChars;
                }
            }

            byte[] byteString = new byte[hexChars + 1 >> 1];
            int pos = hexChars & 1;

            for (int i = 0; i < rawChars.Length; ++i)
            {
                if (rawChars[i] >= '0' && rawChars[i] <= '9')
                {
                    byteString[pos >> 1] = (byte)(byteString[pos >> 1] << 4);
                    byteString[pos >> 1] = (byte)(byteString[pos >> 1] | rawChars[i] - 48);
                }
                else
                {
                    if (rawChars[i] < 'A' || rawChars[i] > 'F')
                    {
                        continue;
                    }

                    byteString[pos >> 1] = (byte)(byteString[pos >> 1] << 4);
                    byteString[pos >> 1] = (byte)(byteString[pos >> 1] | rawChars[i] - 65 + 10);
                }

                ++pos;
            }

            return byteString;
        } 

        public static string ToHexString(Byte[] byteArray)
        {
            var sb = new StringBuilder(byteArray.Length);
            for (int i = 0; i < byteArray.Length; i++)
            {
                sb.Append(byteArray[i].ToString("X2"));
            }
            return sb.ToString();
        }

        public static string ToHexString(byte[] bytes, string prefix, string span)
        { 
            StringBuilder sb = new StringBuilder(bytes.Length * (2 + span.Length));
            sb.Append(prefix);
            bool isFirst = true;
            foreach (byte b in bytes)
            {
                if (isFirst)
                {
                    isFirst = false;
                }
                else
                {
                    sb.Append(span);
                }
                sb.Append(Convert.ToString(b, 16).PadLeft(2, '0').ToUpper());
            }
            return sb.ToString();
        }

           
    }
}
